home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / dix / gc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-14  |  26.8 KB  |  1,200 lines

  1. /***********************************************************
  2. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* $XConsortium: gc.c,v 5.12 89/10/08 15:14:29 rws Exp $ */
  26.  
  27. #include "X.h"
  28. #include "Xmd.h"
  29. #include "Xproto.h"
  30. #include "misc.h"
  31. #include "resource.h"
  32. #include "gcstruct.h"
  33. #include "pixmapstr.h"
  34. #include "dixfontstr.h"
  35. #include "scrnintstr.h"
  36. #include "region.h"
  37.  
  38. #include "dix.h"
  39.  
  40. extern XID clientErrorValue;
  41.  
  42. #ifdef DEBUG
  43. extern void NotImplemented();
  44. #endif
  45.  
  46. static Bool CreateDefaultTile();
  47.  
  48. unsigned char DefaultDash[2] = {4, 4};
  49.  
  50. void
  51. ValidateGC(pDraw, pGC)
  52.     DrawablePtr    pDraw;
  53.     GC        *pGC;
  54. {
  55.     (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw);
  56.     pGC->stateChanges = 0;
  57.     pGC->serialNumber = pDraw->serialNumber;
  58. }
  59.  
  60.  
  61.  
  62. /* Publically defined entry to ChangeGC.  Just calls DoChangeGC and tells
  63.  * it that all of the entries are constants or IDs */
  64. int
  65. ChangeGC(pGC, mask, pval)
  66.     register GC     *pGC;
  67.     register BITS32    mask;
  68.     XID            *pval;
  69. {
  70.     return (DoChangeGC(pGC, mask, pval, 0));
  71. }
  72. /* DoChangeGC(pGC, mask, pval, fPointer)
  73.    mask is a set of bits indicating which values to change.
  74.    pval contains an appropriate value for each mask.
  75.    fPointer is true if the values for tiles, stipples, fonts or clipmasks
  76.    are pointers instead of IDs.  
  77.    if there is an error, the value is marked as changed 
  78.    anyway, which is probably wrong, but infrequent.
  79.  
  80. NOTE:
  81.     all values sent over the protocol for ChangeGC requests are
  82. 32 bits long
  83. */
  84.  
  85. int
  86. DoChangeGC(pGC, mask, pval, fPointer)
  87.     register GC     *pGC;
  88.     register BITS32    mask;
  89.     XID            *pval;
  90.     int            fPointer;
  91. {
  92.     register BITS32     index;
  93.     register int     error = 0;
  94.     PixmapPtr         pPixmap;
  95.     BITS32        maskQ;
  96.  
  97.     pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
  98.  
  99.     maskQ = mask;    /* save these for when we walk the GCque */
  100.     while (mask && !error) 
  101.     {
  102.     index = (BITS32) lowbit (mask);
  103.     mask &= ~index;
  104.     pGC->stateChanges |= index;
  105.     switch (index)
  106.     {
  107.         case GCFunction:
  108.         if (((CARD8)*pval >= GXclear) && ((CARD8)*pval <= GXset))
  109.             pGC->alu = (CARD8)*pval;
  110.         else
  111.         {
  112.             clientErrorValue = (CARD8)*pval;
  113.             error = BadValue;
  114.         }
  115.         pval++;
  116.         break;
  117.         case GCPlaneMask:
  118.         pGC->planemask = *pval++;
  119.         break;
  120.         case GCForeground:
  121.         pGC->fgPixel = *pval++;
  122.         /*
  123.          * this is for CreateGC
  124.          */
  125.         if (!pGC->tileIsPixel && pGC->tile.pixmap == None)
  126.         {
  127.             pGC->tileIsPixel = TRUE;
  128.             pGC->tile.pixel = pGC->fgPixel;
  129.         }
  130.         break;
  131.         case GCBackground:
  132.         pGC->bgPixel = *pval++;
  133.         break;
  134.         case GCLineWidth:        /* ??? line width is a CARD16 */
  135.         pGC->lineWidth = (CARD16)*pval;
  136.                 pval++;
  137.         break;
  138.         case GCLineStyle:
  139.         if (((CARD8)*pval >= LineSolid) 
  140.             && ((CARD8)*pval <= LineDoubleDash))
  141.             pGC->lineStyle = (CARD8)*pval;
  142.         else
  143.         {
  144.             clientErrorValue = (CARD8)*pval;
  145.             error = BadValue;
  146.         }
  147.         pval++;
  148.         break;
  149.         case GCCapStyle:
  150.         if (((CARD8)*pval >= CapNotLast) 
  151.             && ((CARD8)*pval <= CapProjecting))
  152.             pGC->capStyle = (CARD8)*pval;
  153.         else
  154.         {
  155.             clientErrorValue = (CARD8)*pval;
  156.             error = BadValue;
  157.         }
  158.         pval++;
  159.         break;
  160.         case GCJoinStyle:
  161.         if (((CARD8)*pval >= JoinMiter) && ((CARD8)*pval <= JoinBevel))
  162.             pGC->joinStyle = (CARD8)*pval;
  163.         else
  164.         {
  165.             clientErrorValue = (CARD8)*pval;
  166.             error = BadValue;
  167.         }
  168.         pval++;
  169.         break;
  170.         case GCFillStyle:
  171.         if (((CARD8)*pval >= FillSolid) 
  172.             && ((CARD8)*pval <= FillOpaqueStippled))
  173.             pGC->fillStyle = (CARD8)*pval;
  174.         else
  175.         {
  176.             clientErrorValue = (CARD8)*pval;
  177.             error = BadValue;
  178.         }
  179.         pval++;
  180.         break;
  181.         case GCFillRule:
  182.         if (((CARD8)*pval >= EvenOddRule) && 
  183.             ((CARD8)*pval <= WindingRule))
  184.             pGC->fillRule = (CARD8)*pval;
  185.         else
  186.         {
  187.             clientErrorValue = (CARD8)*pval;
  188.             error = BadValue;
  189.         }
  190.         pval++;
  191.         break;
  192.         case GCTile:
  193.         if(fPointer)
  194.             pPixmap = (PixmapPtr) *pval;
  195.         else
  196.             pPixmap = (PixmapPtr)LookupIDByType((CARD32)*pval, 
  197.                             RT_PIXMAP);
  198.         if (pPixmap)
  199.         {
  200.             if ((pPixmap->drawable.depth != pGC->depth) ||
  201.             (pPixmap->drawable.pScreen != pGC->pScreen))
  202.             {
  203.             error = BadMatch;
  204.             }
  205.             else
  206.             {
  207.             pPixmap->refcnt++;
  208.             if (!pGC->tileIsPixel)
  209.                 (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
  210.             pGC->tileIsPixel = FALSE;
  211.             pGC->tile.pixmap = pPixmap;
  212.             }
  213.         }
  214.         else
  215.         {
  216.             clientErrorValue = (CARD32)*pval;
  217.             error = BadPixmap;
  218.         }
  219.         pval++;
  220.         break;
  221.         case GCStipple:
  222.         if(fPointer)
  223.             pPixmap = (PixmapPtr) *pval;
  224.         else
  225.             pPixmap = (PixmapPtr)LookupIDByType((CARD32)*pval, 
  226.                             RT_PIXMAP);
  227.         if (pPixmap)
  228.         {
  229.             if ((pPixmap->drawable.depth != 1) ||
  230.             (pPixmap->drawable.pScreen != pGC->pScreen))
  231.             {
  232.             error = BadMatch;
  233.             }
  234.             else
  235.             {
  236.             pPixmap->refcnt++;
  237.             if (pGC->stipple)
  238.                 (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
  239.             pGC->stipple = pPixmap;
  240.             }
  241.         }
  242.         else
  243.         {
  244.             clientErrorValue = (CARD32)*pval;
  245.             error = BadPixmap;
  246.         }
  247.         pval++;
  248.         break;
  249.         case GCTileStipXOrigin:
  250.         pGC->patOrg.x = (INT16)*pval;
  251.                 pval++;
  252.         break;
  253.         case GCTileStipYOrigin:
  254.         pGC->patOrg.y = (INT16)*pval;
  255.         pval++;
  256.         break;
  257.         case GCFont:
  258.               {
  259.         FontPtr    pFont;
  260.  
  261.  
  262.         if(fPointer)
  263.             pFont = (FontPtr) *pval;
  264.         else
  265.             pFont = (FontPtr)LookupIDByType((CARD32)*pval, RT_FONT);
  266.  
  267.         if (pFont)
  268.         {
  269.             pFont->refcnt++;
  270.             if (pGC->font)
  271.                     CloseFont(pGC->font, (Font)0);
  272.             pGC->font = pFont;
  273.          }
  274.         else
  275.         {
  276.             clientErrorValue = *pval;
  277.             error = BadFont;
  278.         }
  279.         pval++;
  280.         break;
  281.           }
  282.         case GCSubwindowMode:
  283.         if (((CARD8)*pval == ClipByChildren) ||
  284.             ((CARD8)*pval == IncludeInferiors))
  285.             pGC->subWindowMode = (CARD8)*pval;
  286.         else
  287.         {
  288.             clientErrorValue = (CARD8)*pval;
  289.             error = BadValue;
  290.         }
  291.         pval++;
  292.         break;
  293.         case GCGraphicsExposures:
  294.         if ((Bool)*pval == xFalse)
  295.             pGC->graphicsExposures = FALSE;
  296.         else if ((Bool)*pval == xTrue)
  297.             pGC->graphicsExposures = TRUE;
  298.         else
  299.         {
  300.             clientErrorValue = (Bool)*pval;
  301.             error = BadValue;
  302.         }
  303.         pval++;
  304.         break;
  305.         case GCClipXOrigin:
  306.         pGC->clipOrg.x = (INT16)(*pval);
  307.         pval++;
  308.         break;
  309.         case GCClipYOrigin:
  310.         pGC->clipOrg.y = (INT16)(*pval);
  311.         pval++;
  312.         break;
  313.         case GCClipMask:
  314.           {
  315.         Pixmap pid;
  316.         int    clipType;
  317.  
  318.         pid = (Pixmap) *pval;
  319.         if (pid == None)
  320.         {
  321.             clipType = CT_NONE;
  322.         }
  323.         else
  324.         {
  325.             if(fPointer)
  326.             pPixmap = (PixmapPtr) *pval;
  327.             else
  328.                 pPixmap = (PixmapPtr)LookupIDByType(pid, RT_PIXMAP);
  329.             if (pPixmap)
  330.               {
  331.             if ((pPixmap->drawable.depth != 1) ||
  332.                 (pPixmap->drawable.pScreen != pGC->pScreen))
  333.             {
  334.                 error = BadMatch;
  335.             }
  336.             else
  337.             {
  338.                 clipType = CT_PIXMAP;
  339.                 pPixmap->refcnt++;
  340.             }
  341.             }
  342.             else
  343.             {
  344.             clientErrorValue = pid;
  345.             error = BadPixmap;
  346.             }
  347.         }
  348.         pval++;
  349.         if(error == Success)
  350.         {
  351.             (*pGC->funcs->ChangeClip)(pGC, clipType, pPixmap, 0);
  352.         }
  353.         break;
  354.           }
  355.         case GCDashOffset:
  356.         pGC->dashOffset = (CARD16)*pval;
  357.         pval++;
  358.         break;
  359.         case GCDashList:
  360.         if ((CARD8) (*pval) == 4)
  361.         {
  362.             if (pGC->dash != DefaultDash)
  363.             {
  364.             xfree(pGC->dash);
  365.             pGC->numInDashList = 2;
  366.             pGC->dash = DefaultDash;
  367.             }
  368.         }
  369.         else if ((CARD8) (*pval) != 0)
  370.          {
  371.             unsigned char *dash;
  372.  
  373.             dash = (unsigned char *)xalloc(2 * sizeof(unsigned char));
  374.             if (dash)
  375.             {
  376.             if (pGC->dash != DefaultDash)
  377.                 xfree(pGC->dash);
  378.             pGC->numInDashList = 2;
  379.             pGC->dash = dash;
  380.             dash[0] = (CARD8)(*pval);
  381.             dash[1] = (CARD8)(*pval);
  382.             }
  383.             else
  384.             error = BadAlloc;
  385.         }
  386.          else
  387.         {
  388.            clientErrorValue = (CARD8)*pval;
  389.            error = BadValue;
  390.         }
  391.         pval++;
  392.         break;
  393.         case GCArcMode:
  394.         if (((CARD8)*pval >= ArcChord) 
  395.             && ((CARD8)*pval <= ArcPieSlice))
  396.             pGC->arcMode = (CARD8)*pval;
  397.         else
  398.         {
  399.             clientErrorValue = (CARD8)*pval;
  400.             error = BadValue;
  401.         }
  402.         pval++;
  403.         break;
  404.         default:
  405.         clientErrorValue = maskQ;
  406.         error = BadValue;
  407.         pval++;
  408.         break;
  409.     }
  410.     }
  411.     if (pGC->fillStyle == FillTiled && pGC->tileIsPixel)
  412.     {
  413.     if (!CreateDefaultTile (pGC))
  414.     {
  415.         pGC->fillStyle = FillSolid;
  416.         error = BadAlloc;
  417.     }
  418.     }
  419.     (*pGC->funcs->ChangeGC)(pGC, maskQ);
  420.     return error;
  421. }
  422.  
  423. /* CreateGC(pDrawable, mask, pval, pStatus)
  424.    creates a default GC for the given drawable, using mask to fill
  425.    in any non-default values.
  426.    Returns a pointer to the new GC on success, NULL otherwise.
  427.    returns status of non-default fields in pStatus
  428. BUG:
  429.    should check for failure to create default tile
  430.  
  431. */
  432.  
  433. static int  gcPrivateCount;
  434.  
  435. void
  436. ResetGCPrivates()
  437. {
  438.     gcPrivateCount = 0;
  439. }
  440.  
  441. int
  442. AllocateGCPrivateIndex()
  443. {
  444.     return gcPrivateCount++;
  445. }
  446.  
  447. static GCPtr
  448. AllocateGC(pScreen)
  449.     ScreenPtr pScreen;
  450. {
  451.     GCPtr pGC;
  452.     register char *ptr;
  453.     register DevUnion *ppriv;
  454.     register unsigned *sizes;
  455.     register unsigned size;
  456.     register int i;
  457.  
  458.     pGC = (GCPtr)xalloc(pScreen->totalGCSize);
  459.     if (pGC)
  460.     {
  461.     ppriv = (DevUnion *)(pGC + 1);
  462.     pGC->devPrivates = ppriv;
  463.     sizes = pScreen->GCPrivateSizes;
  464.     ptr = (char *)(ppriv + gcPrivateCount);
  465.     for (i = gcPrivateCount; --i >= 0; ppriv++, sizes++)
  466.     {
  467.         if (size = *sizes)
  468.         {
  469.         ppriv->ptr = (pointer)ptr;
  470.         ptr += size;
  471.         }
  472.         else
  473.         ppriv->ptr = (pointer)NULL;
  474.     }
  475.     }
  476.     return pGC;
  477. }
  478.  
  479. GCPtr
  480. CreateGC(pDrawable, mask, pval, pStatus)
  481.     DrawablePtr    pDrawable;
  482.     BITS32    mask;
  483.     XID        *pval;
  484.     int        *pStatus;
  485. {
  486.     register GCPtr pGC;
  487.     extern FontPtr defaultFont;
  488. #ifdef DEBUG
  489.     void     (**j)();
  490. #endif /* DEBUG */
  491.  
  492.     pGC = AllocateGC(pDrawable->pScreen);
  493.     if (!pGC)
  494.     {
  495.     *pStatus = BadAlloc;
  496.     return (GCPtr)NULL;
  497.     }
  498.  
  499. #ifdef DEBUG
  500.     for(j = &pGC->FillSpans;
  501.         j < &pGC->PushPixels;
  502.         j++ )
  503.         *j = NotImplemented;
  504. #endif /* DEBUG */
  505.  
  506.     pGC->pScreen = pDrawable->pScreen;
  507.     pGC->depth = pDrawable->depth;
  508.     pGC->alu = GXcopy; /* dst <- src */
  509.     pGC->planemask = ~0;
  510.     pGC->serialNumber = GC_CHANGE_SERIAL_BIT;
  511.     pGC->funcs = 0;
  512.  
  513.     pGC->fgPixel = 0;
  514.     pGC->bgPixel = 1;
  515.     pGC->lineWidth = 0;
  516.     pGC->lineStyle = LineSolid;
  517.     pGC->capStyle = CapButt;
  518.     pGC->joinStyle = JoinMiter;
  519.     pGC->fillStyle = FillSolid;
  520.     pGC->fillRule = EvenOddRule;
  521.     pGC->arcMode = ArcPieSlice;
  522.     if (mask & GCForeground)
  523.     {
  524.     /*
  525.      * magic special case -- ChangeGC checks for this condition
  526.      * and snags the Foreground value to create a pseudo default-tile
  527.      */
  528.     pGC->tileIsPixel = FALSE;
  529.     pGC->tile.pixmap = NullPixmap;
  530.     }
  531.     else
  532.     {
  533.     pGC->tileIsPixel = TRUE;
  534.     pGC->tile.pixel = 0;
  535.     }
  536.  
  537.     pGC->patOrg.x = 0;
  538.     pGC->patOrg.y = 0;
  539.     pGC->subWindowMode = ClipByChildren;
  540.     pGC->graphicsExposures = TRUE;
  541.     pGC->clipOrg.x = 0;
  542.     pGC->clipOrg.y = 0;
  543.     pGC->clientClipType = CT_NONE;
  544.     pGC->clientClip = (pointer)NULL;
  545.     pGC->numInDashList = 2;
  546.     pGC->dash = DefaultDash;
  547.     pGC->dashOffset = 0;
  548.     pGC->lastWinOrg.x = 0;
  549.     pGC->lastWinOrg.y = 0;
  550.  
  551.     /* use the default font and stipple */
  552.     pGC->font = defaultFont;
  553.     defaultFont->refcnt++;
  554.     pGC->stipple = pGC->pScreen->PixmapPerDepth[0];
  555.     pGC->stipple->refcnt++;
  556.  
  557.     pGC->stateChanges = (1 << GCLastBit+1) - 1;
  558.     if (!(*pGC->pScreen->CreateGC)(pGC))
  559.     *pStatus = BadAlloc;
  560.     else if (mask)
  561.         *pStatus = ChangeGC(pGC, mask, pval);
  562.     else
  563.     *pStatus = Success;
  564.     if (*pStatus != Success)
  565.     {
  566.     FreeGC(pGC, (GContext)0);
  567.     pGC = (GCPtr)NULL;
  568.     }
  569.  
  570.     return (pGC);
  571. }
  572.  
  573. static Bool
  574. CreateDefaultTile (pGC)
  575.     GCPtr   pGC;
  576. {
  577.     XID        tmpval[3];
  578.     PixmapPtr     pTile;
  579.     GCPtr    pgcScratch;
  580.     xRectangle    rect;
  581.     short    w, h;
  582.  
  583.     w = 1;
  584.     h = 1;
  585.     (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h);
  586.     pTile = (PixmapPtr)
  587.         (*pGC->pScreen->CreatePixmap)(pGC->pScreen,
  588.                       w, h, pGC->depth);
  589.     pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen);
  590.     if (!pTile || !pgcScratch)
  591.     {
  592.     if (pTile)
  593.         (*pTile->drawable.pScreen->DestroyPixmap)(pTile);
  594.     if (pgcScratch)
  595.         FreeScratchGC(pgcScratch);
  596.     return FALSE;
  597.     }
  598.     tmpval[0] = GXcopy;
  599.     tmpval[1] = pGC->tile.pixel;
  600.     tmpval[2] = FillSolid;
  601.     (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, 
  602.            tmpval);
  603.     ValidateGC((DrawablePtr)pTile, pgcScratch);
  604.     rect.x = 0;
  605.     rect.y = 0;
  606.     rect.width = w;
  607.     rect.height = h;
  608.     (*pgcScratch->ops->PolyFillRect)(pTile, pgcScratch, 1, &rect);
  609.     /* Always remember to free the scratch graphics context after use. */
  610.     FreeScratchGC(pgcScratch);
  611.  
  612.     pGC->tileIsPixel = FALSE;
  613.     pGC->tile.pixmap = pTile;
  614.     return TRUE;
  615. }
  616.  
  617. int
  618. CopyGC(pgcSrc, pgcDst, mask)
  619.     register GC        *pgcSrc;
  620.     register GC        *pgcDst;
  621.     register BITS32    mask;
  622. {
  623.     register BITS32    index;
  624.     BITS32        maskQ;
  625.     int i;
  626.     int         error = 0;
  627.  
  628.     if (pgcSrc == pgcDst)
  629.     return Success;
  630.     pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
  631.     pgcDst->stateChanges |= mask;
  632.     maskQ = mask;
  633.     while (mask)
  634.     {
  635.     index = (BITS32) lowbit (mask);
  636.     mask &= ~index;
  637.     switch (index)
  638.     {
  639.         case GCFunction:
  640.         pgcDst->alu = pgcSrc->alu;
  641.         break;
  642.         case GCPlaneMask:
  643.         pgcDst->planemask = pgcSrc->planemask;
  644.         break;
  645.         case GCForeground:
  646.         pgcDst->fgPixel = pgcSrc->fgPixel;
  647.         break;
  648.         case GCBackground:
  649.         pgcDst->bgPixel = pgcSrc->bgPixel;
  650.         break;
  651.         case GCLineWidth:
  652.         pgcDst->lineWidth = pgcSrc->lineWidth;
  653.         break;
  654.         case GCLineStyle:
  655.         pgcDst->lineStyle = pgcSrc->lineStyle;
  656.         break;
  657.         case GCCapStyle:
  658.         pgcDst->capStyle = pgcSrc->capStyle;
  659.         break;
  660.         case GCJoinStyle:
  661.         pgcDst->joinStyle = pgcSrc->joinStyle;
  662.         break;
  663.         case GCFillStyle:
  664.         pgcDst->fillStyle = pgcSrc->fillStyle;
  665.         break;
  666.         case GCFillRule:
  667.         pgcDst->fillRule = pgcSrc->fillRule;
  668.         break;
  669.         case GCTile:
  670.         {
  671.             if (EqualPixUnion(pgcDst->tileIsPixel,
  672.                       pgcDst->tile,
  673.                       pgcSrc->tileIsPixel,
  674.                       pgcSrc->tile))
  675.             {
  676.             break;
  677.             }
  678.             if (!pgcDst->tileIsPixel)
  679.             (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap);
  680.             pgcDst->tileIsPixel = pgcSrc->tileIsPixel;
  681.             pgcDst->tile = pgcSrc->tile;
  682.             if (!pgcDst->tileIsPixel)
  683.                pgcDst->tile.pixmap->refcnt++;
  684.             break;
  685.         }
  686.         case GCStipple:
  687.         {
  688.             if (pgcDst->stipple == pgcSrc->stipple)
  689.             break;
  690.             if (pgcDst->stipple)
  691.             (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple);
  692.             pgcDst->stipple = pgcSrc->stipple;
  693.             if (pgcDst->stipple)
  694.             pgcDst->stipple->refcnt ++;
  695.             break;
  696.         }
  697.         case GCTileStipXOrigin:
  698.         pgcDst->patOrg.x = pgcSrc->patOrg.x;
  699.         break;
  700.         case GCTileStipYOrigin:
  701.         pgcDst->patOrg.y = pgcSrc->patOrg.y;
  702.         break;
  703.         case GCFont:
  704.         if (pgcDst->font == pgcSrc->font)
  705.             break;
  706.         if (pgcDst->font)
  707.             CloseFont(pgcDst->font, (Font)0);
  708.         if ((pgcDst->font = pgcSrc->font) != NullFont)
  709.             (pgcDst->font)->refcnt++;
  710.         break;
  711.         case GCSubwindowMode:
  712.         pgcDst->subWindowMode = pgcSrc->subWindowMode;
  713.         break;
  714.         case GCGraphicsExposures:
  715.         pgcDst->graphicsExposures = pgcSrc->graphicsExposures;
  716.         break;
  717.         case GCClipXOrigin:
  718.         pgcDst->clipOrg.x = pgcSrc->clipOrg.x;
  719.         break;
  720.         case GCClipYOrigin:
  721.         pgcDst->clipOrg.y = pgcSrc->clipOrg.y;
  722.         break;
  723.         case GCClipMask:
  724.         (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
  725.         break;
  726.         case GCDashOffset:
  727.         pgcDst->dashOffset = pgcSrc->dashOffset;
  728.         break;
  729.         case GCDashList:
  730.         if (pgcSrc->dash == DefaultDash)
  731.         {
  732.             if (pgcDst->dash != DefaultDash)
  733.             {
  734.             xfree(pgcDst->dash);
  735.             pgcDst->numInDashList = pgcSrc->numInDashList;
  736.             pgcDst->dash = pgcSrc->dash;
  737.             }
  738.         }
  739.         else
  740.         {
  741.             unsigned char *dash;
  742.  
  743.             dash = (unsigned char *)xalloc(pgcSrc->numInDashList *
  744.                            sizeof(unsigned char));
  745.             if (dash)
  746.             {
  747.             if (pgcDst->dash != DefaultDash)
  748.                 xfree(pgcDst->dash);
  749.             pgcDst->numInDashList = pgcSrc->numInDashList;
  750.             pgcDst->dash = dash;
  751.             for (i=0; i<pgcSrc->numInDashList; i++)
  752.                 dash[i] = pgcSrc->dash[i];
  753.             }
  754.             else
  755.             error = BadAlloc;
  756.         }
  757.         break;
  758.         case GCArcMode:
  759.         pgcDst->arcMode = pgcSrc->arcMode;
  760.         break;
  761.         default:
  762.         clientErrorValue = maskQ;
  763.         error = BadValue;
  764.         break;
  765.     }
  766.     }
  767.     if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel)
  768.     {
  769.     if (!CreateDefaultTile (pgcDst))
  770.     {
  771.         pgcDst->fillStyle = FillSolid;
  772.         error = BadAlloc;
  773.     }
  774.     }
  775.     (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst);
  776.     return error;
  777. }
  778.  
  779. /*****************
  780.  * FreeGC 
  781.  *   does the diX part of freeing the characteristics in the GC 
  782.  ***************/
  783.  
  784. /*ARGSUSED*/
  785. int
  786. FreeGC(pGC, gid)
  787.     GCPtr pGC;
  788.     GContext gid;
  789. {
  790.     CloseFont(pGC->font, (Font)0);
  791.     (* pGC->funcs->DestroyClip)(pGC);
  792.  
  793.     if (!pGC->tileIsPixel)
  794.     (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
  795.     if (pGC->stipple)
  796.     (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
  797.  
  798.     (*pGC->funcs->DestroyGC) (pGC);
  799.     if (pGC->dash != DefaultDash)
  800.     xfree(pGC->dash);
  801.     xfree(pGC);
  802.     return(Success);
  803. }
  804.  
  805. void
  806. SetGCMask(pGC, selectMask, newDataMask)
  807.     GCPtr pGC;
  808.     Mask selectMask;
  809.     Mask newDataMask;
  810. {
  811.     pGC->stateChanges = (~selectMask & pGC->stateChanges) |
  812.                 (selectMask & newDataMask);
  813.     if (selectMask & newDataMask)
  814.         pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;        
  815. }
  816.  
  817.  
  818.  
  819. /* CreateScratchGC(pScreen, depth)
  820.     like CreateGC, but doesn't do the default tile or stipple,
  821. since we can't create them without already having a GC.  any code
  822. using the tile or stipple has to set them explicitly anyway,
  823. since the state of the scratch gc is unknown.  This is OK
  824. because ChangeGC() has to be able to deal with NULL tiles and
  825. stipples anyway (in case the CreateGC() call has provided a 
  826. value for them -- we can't set the default tile until the
  827. client-supplied attributes are installed, since the fgPixel
  828. is what fills the default tile.  (maybe this comment should
  829. go with CreateGC() or ChangeGC().)
  830. */
  831.  
  832. GCPtr
  833. CreateScratchGC(pScreen, depth)
  834.     ScreenPtr pScreen;
  835.     unsigned depth;
  836. {
  837.     register GCPtr pGC;
  838.     extern FontPtr defaultFont;
  839. #ifdef DEBUG
  840.     void     (**j)();
  841. #endif /* DEBUG */
  842.  
  843.     pGC = AllocateGC(pScreen);
  844.     if (!pGC)
  845.     return (GCPtr)NULL;
  846.  
  847. #ifdef DEBUG
  848.     for(j = &pGC->FillSpans;
  849.         j < &pGC->PushPixels;
  850.         j++ )
  851.         *j = NotImplemented;
  852. #endif /* DEBUG */
  853.  
  854.     pGC->pScreen = pScreen;
  855.     pGC->depth = depth;
  856.     pGC->alu = GXcopy; /* dst <- src */
  857.     pGC->planemask = ~0;
  858.     pGC->serialNumber = 0;
  859.  
  860.     pGC->fgPixel = 0;
  861.     pGC->bgPixel = 1;
  862.     pGC->lineWidth = 0;
  863.     pGC->lineStyle = LineSolid;
  864.     pGC->capStyle = CapButt;
  865.     pGC->joinStyle = JoinMiter;
  866.     pGC->fillStyle = FillSolid;
  867.     pGC->fillRule = EvenOddRule;
  868.     pGC->arcMode = ArcPieSlice;
  869.     pGC->font = defaultFont;
  870.     if ( pGC->font)  /* necessary, because open of default font could fail */
  871.     pGC->font->refcnt++;
  872.     pGC->tileIsPixel = TRUE;
  873.     pGC->tile.pixel = 0;
  874.     pGC->stipple = NullPixmap;
  875.     pGC->patOrg.x = 0;
  876.     pGC->patOrg.y = 0;
  877.     pGC->subWindowMode = ClipByChildren;
  878.     pGC->graphicsExposures = TRUE;
  879.     pGC->clipOrg.x = 0;
  880.     pGC->clipOrg.y = 0;
  881.     pGC->clientClipType = CT_NONE;
  882.     pGC->dashOffset = 0;
  883.     pGC->numInDashList = 2;
  884.     pGC->dash = DefaultDash;
  885.     pGC->lastWinOrg.x = 0;
  886.     pGC->lastWinOrg.y = 0;
  887.  
  888.     pGC->stateChanges = (1 << GCLastBit+1) - 1;
  889.     if (!(*pScreen->CreateGC)(pGC))
  890.     {
  891.     FreeGC(pGC, (GContext)0);
  892.     pGC = (GCPtr)NULL;
  893.     }
  894.     return pGC;
  895. }
  896.  
  897.  
  898. FreeGCperDepth(screenNum)
  899.     int screenNum;
  900. {
  901.     register int i;
  902.     register ScreenPtr pScreen;
  903.     GCPtr *ppGC;
  904.  
  905.     pScreen = screenInfo.screens[screenNum];
  906.     ppGC = pScreen->GCperDepth;
  907.  
  908.     for (i = 0; i <= pScreen->numDepths; i++)
  909.     (void)FreeGC(ppGC[i], (GContext)0);
  910.     pScreen->rgf = ~0L;
  911. }
  912.  
  913.  
  914. Bool
  915. CreateGCperDepth(screenNum)
  916.     int screenNum;
  917. {
  918.     register int i;
  919.     register ScreenPtr pScreen;
  920.     DepthPtr pDepth;
  921.     GCPtr *ppGC;
  922.  
  923.     pScreen = screenInfo.screens[screenNum];
  924.     pScreen->rgf = 0;
  925.     ppGC = pScreen->GCperDepth;
  926.     /* do depth 1 separately because it's not included in list */
  927.     if (!(ppGC[0] = CreateScratchGC(pScreen, 1)))
  928.     return FALSE;
  929.     ppGC[0]->graphicsExposures = FALSE;
  930.  
  931.     pDepth = pScreen->allowedDepths;
  932.     for (i=0; i<pScreen->numDepths; i++, pDepth++)
  933.     {
  934.     if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth)))
  935.     {
  936.         for (; i >= 0; i--)
  937.         (void)FreeGC(ppGC[i], (GContext)0);
  938.         return FALSE;
  939.     }
  940.     ppGC[i+1]->graphicsExposures = FALSE;
  941.     }
  942.     return TRUE;
  943. }
  944.  
  945. Bool
  946. CreateDefaultStipple(screenNum)
  947.     int screenNum;
  948. {
  949.     register ScreenPtr pScreen;
  950.     XID tmpval[3];
  951.     xRectangle rect;
  952.     short w, h;
  953.     GCPtr pgcScratch;
  954.  
  955.     pScreen = screenInfo.screens[screenNum];
  956.  
  957.     w = 16;
  958.     h = 16;
  959.     (* pScreen->QueryBestSize)(StippleShape, &w, &h);
  960.     if (!(pScreen->PixmapPerDepth[0] =
  961.             (*pScreen->CreatePixmap)(pScreen, w, h, 1)))
  962.     return FALSE;
  963.     /* fill stipple with 1 */
  964.     tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid;
  965.     pgcScratch = GetScratchGC(1, pScreen);
  966.     if (!pgcScratch)
  967.     {
  968.     (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
  969.     return FALSE;
  970.     }
  971.     (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval);
  972.     ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch);
  973.     rect.x = 0;
  974.     rect.y = 0;
  975.     rect.width = w;
  976.     rect.height = h;
  977.     (*pgcScratch->ops->PolyFillRect)(pScreen->PixmapPerDepth[0], 
  978.                 pgcScratch, 1, &rect);
  979.     FreeScratchGC(pgcScratch);
  980.     return TRUE;
  981. }
  982.  
  983. FreeDefaultStipple(screenNum)
  984.     int screenNum;
  985. {
  986.     ScreenPtr pScreen = screenInfo.screens[screenNum];
  987.     (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
  988. }
  989.  
  990.  
  991. SetDashes(pGC, offset, ndash, pdash)
  992. register GCPtr pGC;
  993. unsigned offset;
  994. register unsigned ndash;
  995. register unsigned char *pdash;
  996. {
  997.     register long i;
  998.     register unsigned char *p;
  999.     BITS32 maskQ = 0;
  1000.  
  1001.     i = ndash;
  1002.     p = pdash;
  1003.     while (i--)
  1004.     {
  1005.     if (!*p++)
  1006.     {
  1007.         /* dash segment must be > 0 */
  1008.         clientErrorValue = 0;
  1009.         return BadValue;
  1010.     }
  1011.     }
  1012.  
  1013.     p = (unsigned char *)xalloc(ndash * sizeof(unsigned char));
  1014.     if (!p)
  1015.     return BadAlloc;
  1016.  
  1017.     pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
  1018.     if (offset != pGC->dashOffset)
  1019.     {
  1020.     pGC->dashOffset = offset;
  1021.     pGC->stateChanges |= GCDashOffset;
  1022.     maskQ |= GCDashOffset;
  1023.     }
  1024.  
  1025.     if (pGC->dash != DefaultDash)
  1026.     xfree(pGC->dash);
  1027.     pGC->numInDashList = ndash;
  1028.     pGC->dash = p;
  1029.     while(ndash--)
  1030.     *p++ = *pdash++;
  1031.     pGC->stateChanges |= GCDashList;
  1032.     maskQ |= GCDashList;
  1033.  
  1034.     if (pGC->funcs->ChangeGC)
  1035.     (*pGC->funcs->ChangeGC) (pGC, maskQ);
  1036.     return Success;
  1037. }
  1038.  
  1039. int
  1040. VerifyRectOrder(nrects, prects, ordering)
  1041.     int            nrects;
  1042.     xRectangle        *prects;
  1043.     int            ordering;
  1044. {
  1045.     register xRectangle    *prectP, *prectN;
  1046.     register int    i;
  1047.  
  1048.     switch(ordering)
  1049.     {
  1050.       case Unsorted:
  1051.       return CT_UNSORTED;
  1052.       case YSorted:
  1053.       if(nrects > 1)
  1054.       {
  1055.           for(i = 1, prectP = prects, prectN = prects + 1;
  1056.           i < nrects;
  1057.           i++, prectP++, prectN++)
  1058.           if(prectN->y < prectP->y)
  1059.               return -1;
  1060.       }
  1061.       return CT_YSORTED;
  1062.       case YXSorted:
  1063.       if(nrects > 1)
  1064.       {
  1065.           for(i = 1, prectP = prects, prectN = prects + 1;
  1066.           i < nrects;
  1067.           i++, prectP++, prectN++)
  1068.           if((prectN->y < prectP->y) ||
  1069.               ( (prectN->y == prectP->y) &&
  1070.                 (prectN->x < prectP->x) ) )
  1071.               return -1;
  1072.       }
  1073.       return CT_YXSORTED;
  1074.       case YXBanded:
  1075.       if(nrects > 1)
  1076.       {
  1077.           for(i = 1, prectP = prects, prectN = prects + 1;
  1078.           i < nrects;
  1079.           i++, prectP++, prectN++)
  1080.           if((prectN->y != prectP->y &&
  1081.                prectN->y < prectP->y + (int) prectP->height) ||
  1082.              ((prectN->y == prectP->y) &&
  1083.               (prectN->height != prectP->height ||
  1084.                prectN->x < prectP->x + (int) prectP->width)))
  1085.               return -1;
  1086.       }
  1087.       return CT_YXBANDED;
  1088.     }
  1089.     return -1;
  1090. }
  1091.  
  1092. int
  1093. SetClipRects(pGC, xOrigin, yOrigin, nrects, prects, ordering)
  1094.     GCPtr        pGC;
  1095.     int            xOrigin, yOrigin;
  1096.     int            nrects;
  1097.     xRectangle        *prects;
  1098.     int            ordering;
  1099. {
  1100.     int            newct, size;
  1101.     xRectangle         *prectsNew;
  1102.  
  1103.     newct = VerifyRectOrder(nrects, prects, ordering);
  1104.     if (newct < 0)
  1105.     return(BadMatch);
  1106.     size = nrects * sizeof(xRectangle);
  1107.     prectsNew = (xRectangle *) xalloc(size);
  1108.     if (!prects && size)
  1109.     return BadAlloc;
  1110.  
  1111.     pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
  1112.     pGC->clipOrg.x = xOrigin;
  1113.     pGC->stateChanges |= GCClipXOrigin;
  1114.          
  1115.     pGC->clipOrg.y = yOrigin;
  1116.     pGC->stateChanges |= GCClipYOrigin;
  1117.  
  1118.     if (size)
  1119.     bcopy((char *)prects, (char *)prectsNew, size);
  1120.     (*pGC->funcs->ChangeClip)(pGC, newct, prectsNew, nrects);
  1121.     if (pGC->funcs->ChangeGC)
  1122.     (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask);
  1123.     return Success;
  1124. }
  1125.  
  1126.  
  1127. /*
  1128.    sets reasonable defaults 
  1129.    if we can get a pre-allocated one, use it and mark it as used.
  1130.    if we can't, create one out of whole cloth (The Velveteen GC -- if
  1131.    you use it often enough it will become real.)
  1132. */
  1133. GCPtr
  1134. GetScratchGC(depth, pScreen)
  1135.     register unsigned depth;
  1136.     register ScreenPtr pScreen;
  1137. {
  1138.     register int i;
  1139.     register GCPtr pGC;
  1140.  
  1141.     for (i=0; i<=pScreen->numDepths; i++)
  1142.         if ( pScreen->GCperDepth[i]->depth == depth &&
  1143.          !(pScreen->rgf & (1L << (i+1)))
  1144.        )
  1145.     {
  1146.         pScreen->rgf |= (1L << (i+1));
  1147.             pGC = (pScreen->GCperDepth[i]);
  1148.  
  1149.         pGC->alu = GXcopy;
  1150.         pGC->planemask = ~0;
  1151.         pGC->serialNumber = 0;
  1152.         pGC->fgPixel = 0;
  1153.         pGC->bgPixel = 1;
  1154.         pGC->lineWidth = 0;
  1155.         pGC->lineStyle = LineSolid;
  1156.         pGC->capStyle = CapButt;
  1157.         pGC->joinStyle = JoinMiter;
  1158.         pGC->fillStyle = FillSolid;
  1159.         pGC->fillRule = EvenOddRule;
  1160.         pGC->arcMode = ArcChord;
  1161.         pGC->patOrg.x = 0;
  1162.         pGC->patOrg.y = 0;
  1163.         pGC->subWindowMode = ClipByChildren;
  1164.         pGC->graphicsExposures = FALSE;
  1165.         pGC->clipOrg.x = 0;
  1166.         pGC->clipOrg.y = 0;
  1167.         /* can't change clip type, because we might drop storage */
  1168.         pGC->stateChanges = (1 << GCLastBit+1) - 1;
  1169.         return pGC;
  1170.     }
  1171.     /* if we make it this far, need to roll our own */
  1172.     pGC = CreateScratchGC(pScreen, depth);
  1173.     if (pGC)
  1174.     pGC->graphicsExposures = FALSE;
  1175.     return pGC;
  1176. }
  1177.  
  1178. /*
  1179.    if the gc to free is in the table of pre-existing ones,
  1180. mark it as available.
  1181.    if not, free it for real
  1182. */
  1183. void
  1184. FreeScratchGC(pGC)
  1185.     register GCPtr pGC;
  1186. {
  1187.     register ScreenPtr pScreen = pGC->pScreen;
  1188.     register int i;
  1189.  
  1190.     for (i=0; i<=pScreen->numDepths; i++)
  1191.     {
  1192.         if ( pScreen->GCperDepth[i] == pGC)
  1193.     {
  1194.         pScreen->rgf &= ~(1L << (i+1));
  1195.         return;
  1196.     }
  1197.     }
  1198.     (void)FreeGC(pGC, (GContext)0);
  1199. }
  1200.